package ModelAndController;
//A kompozit hálózati elemet megvalósító osztály.
//Exception 180 es 199 kozott
public class Composite extends Element{
	//referencia az ütemezőre
	protected Scheduler scheduler;
	//a hálózati elemek osztály referenciája
	protected CircuitElements circuitElements;
	//a listázás részletességét vezérlő bool
	protected boolean shouldListDetails;
	//a soremelés karaktert tartalmazó változó
	protected String newLine;
	//konstruktor
	public Composite(CircuitElements copy, int nbOfMaxUpdates){
		circuitElements = copy;
		scheduler = new Scheduler(copy);
		scheduler.setNbOfMaxUpdates(nbOfMaxUpdates);
		newLine = System.getProperty("line.separator");
	}
	//a részletességet beállító függvény
	public void setIfShouldListDetails(boolean copyShouldListDetails){
		shouldListDetails = copyShouldListDetails;
	}
	//Az elem belső állapotának változását végzi a bemenetek értékének függvényében.
	//Ha az adott elem változott, akkor azt jelzi a visszatérési értéken.
	public boolean isUpdateSuccess() throws Exception{
		try{
			boolean retValue = false;
			buffer = "";
			if( circuitElements.checkIfAnyInputGateShouldUpdate() ){
				if( shouldListDetails ){
					int[] temp = new int[1]; temp[0] = -1;
					retValue = scheduler.isUpdateResultStableCircuit(shouldListDetails, temp);
					buffer = newLine+scheduler.getBuffer();
				}
				else
					retValue = scheduler.isUpdateResultStableCircuit(shouldListDetails, null);
				if(retValue = false)
					throw new Exception("260 "+buffer);
			}
			if( !shouldListDetails )
				initBuffer();
			else
				buffer = buffer.concat(newLine);
			return retValue;
		}catch(Exception e){
			if(e.getMessage().startsWith("260") && shouldListDetails )
				throw new Exception(260+" "+buffer+" "+newLine+scheduler.getBuffer()+" "+e.getMessage().replaceFirst("260", ""));
			if(e.getMessage().startsWith("260") && shouldListDetails )
				throw new Exception(260+" "+buffer+" "+e.getMessage().replaceFirst("260", ""));
			throw e;
		}
	}
	//a részletes listázást letiltó függvény
	public void stopListingDetails(){
		shouldListDetails = false;
	}
	//ha a circuitElements tomb nem letezik,hibát dob,
	//egyébként visszaadja a kompozit aktuális kapujának az állapotát
	public int getState(int nbOfOutput) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");	
		return circuitElements.getActualOutputGate(nbOfOutput);
	}
	//a bemeneti huzalok számát állítja be
	public void setInputWireNumbers(int nbOfInputWires) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");
		circuitElements.setInputGateNumber(nbOfInputWires);
	}
	//az aktuális bemeneti huzalt állítja be
	public void setActualInputWire(int nbOfWire,Wire act) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");		
		circuitElements.setActualWireToInputGate(nbOfWire, act);
	}
	//Az elem kimeneteinek számát állítja be
	public void setOutputNumbers(int nbOfOutputWires) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");
		circuitElements.setOutputGateNumber(nbOfOutputWires);
	}
	//Az elem kimeneteinek számát adja vissza
	public int getOutputNumbers(){
		return circuitElements.getOutputGateNumber();
	}
	//Az elem kimeneteinek számát állítja be
	public void setOutputWireNumbers(int actOutputWire, int nbOfActualOutput) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");
		circuitElements.setOutputGateWireNumbers(actOutputWire, nbOfActualOutput);
	}
	//az aktuális kimeneti huzalt állítja be
	public void setActualOutputWire(int nbOfWire, int nbOfWirePozition, Wire act) throws Exception{
		if(circuitElements == null)
			throw new Exception("180");
		circuitElements.setWireToActualOutputOnOutputGate(nbOfWire, nbOfWirePozition, act);
	}
	//az üzenetbuffert inicializálja
	private void initBuffer() throws Exception{
		buffer = "";
		int nbOfOutputs = getOutputNumbers();
		for(int act=0; act<nbOfOutputs; act++){
			buffer = buffer.concat( Integer.toString(getState(act)));
			if( act != (nbOfOutputs-1))
				buffer = buffer.concat(",");
		}
	}
	public void check() throws Exception{
		circuitElements.checkCircuitElements();
	}
	//az aktuális bemeneti kapu raferenciáját adja vissza
	public Gate getActualInputGate(int nbOfInputGate) throws Exception{
		return circuitElements.getReferenceToActualInputGate(nbOfInputGate);
	}
	//az aktuális kimeneti kapu raferenciáját adja vissza
	public Gate getActualOutputGate(int nbOfOutputGate) throws Exception{
		return circuitElements.getReferenceToActualOutputGate(nbOfOutputGate);
	}
}